/**
 * Copyright 2019 吉鼎科技.

 * <p>
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * <p>
 * http://www.apache.org/licenses/LICENSE-2.0
 * <p>
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package cn.easyplatform.utils;

import java.text.DecimalFormat;

/**
 * @author <a href="mailto:davidchen@epclouds.com">littleDog</a>
 * @since Oct 14, 2011
 */
public final class CurrencyUtils {

	private static final String[] MAJORS = { " ", " Thousand ", " Million ",
			" Billion ", " Trillion ", " Quadrillion ", " Quintillion " };

	private static final String[] TENS = { " ", " Ten ", " Twenty", " Thirty",
			" Forty", " Fifty", " Sixty", " Seventy", " Eighty", " Ninety" };

	private static final String[] NUMBERS = { " ", "One ", "Two ", "Three ",
			"Four ", "Five ", "Six ", "Seven ", "Eight ", "Nine ", " Ten ",
			" Eleven ", " Twelve ", " Thirteen ", " Fourteen ", " Fifteen ",
			" Sixteen ", " Seventeen ", " Eighteen ", " Nineteen " };

	private static final String[] digit = { "无", "分", "角", "元", "拾", "佰", "仟",
			"万", "拾", "佰", "仟", "亿", "拾", "佰", "仟" };

	private static final String[] capi = { "零", "壹", "贰", "叁", "肆", "伍", "陆",
			"柒", "捌", "玖" };

	private double cValue;

	private double oValue;

	/**
	 * 货币数字形式转换成大写
	 */
	public static String amount2Cn(double money) {
		if (money == 0) {
			return "零元整";
		}
		DecimalFormat df = new DecimalFormat("###0.00");
		char[] c = df.format(money).toCharArray();
		StringBuilder buf = new StringBuilder();
		String reStr = null;
		int cLength = c.length;
		for (int i = 0; i < c.length; i++) {
			String s = "" + c[i];
			if (s.equals(".")) {
				cLength++;
				continue;
			}
			int cp = Integer.parseInt(s);
			buf.append(capi[cp]);
			buf.append(digit[cLength - i - 1]);
		}
		reStr = buf.toString();
		for (int j = 0; j < 2; j++) {
			reStr = reStr.replaceAll("零零", "零");
			reStr = reStr.replaceAll("零亿", "亿");
			reStr = reStr.replaceAll("零万", "万");
			reStr = reStr.replaceAll("零仟", "零");
			reStr = reStr.replaceAll("零佰", "零");
			reStr = reStr.replaceAll("零拾", "零");
			reStr = reStr.replaceAll("零角", "零");
			reStr = reStr.replaceAll("亿万", "亿零");
			reStr = reStr.replaceAll("零分", "元整");
			reStr = reStr.replaceAll("零元", "元");
			reStr = reStr.replaceAll("零零", "零");
			reStr = reStr.replaceAll("角元整", "角整");
			reStr = reStr.replaceAll("元元", "元");
		}
		return reStr;
	}

	/**
	 * 把阿拉伯数字转换为英文大写格式。<br>
	 * 例如：123.01：One Hundred Twenty Three Dollars And One Cent
	 * 
	 * @param value
	 * @return
	 */
	public static String amount2En(double value) {
		return new CurrencyUtils().format(value);
	}

	/**
	 * 把阿拉伯数字转换为英文大写格式。<br>
	 * 例如：123.01：One Hundred Twenty Three Dollars And One Cent
	 * 
	 * @param value
	 * @return
	 */
	private String format(double value) {
		// double number = CommonUtils.round(value, 2);// 小数点保留两位
		// String result = getDollarPart(number) + getCentPart(number);
		this.cValue = value;
		this.oValue = value;
		String result = "";
		if (this.oValue > 1) {
			result = getCentPart(value);
			if (result.equals(" only "))
				result = getDollarPart(value) + result;
			else
				result = getDollarPart(value) + " and " + result;
		} else
			result = getDollarPart(value) + getCentPart(value);
		if (this.oValue == 0)
			return "ZERO";
		return result.replace("  ", " ").toUpperCase();// 去掉多余的空格，并转为大写
	}

	// 获取整数部分的转换
	private String getDollarPart(double value) {
		int number = (int) value;
		String dollars = formatDigit(number);
		if (dollars.trim().equals(""))
			return "";
		else if (dollars.trim().equals("One"))
			return "One ";
		else
			// return dollars + " Dollars";
			return dollars;

	}

	// 获取小数部分的转换
	private String getCentPart(double number) {
		int cents = (int) (Math.round(number * 100) - ((int) number) * 100);
		String centsPart = formatDigit(cents);

		if (centsPart.trim().equals(""))
			return " only ";
		else if (centsPart.trim().equals("One"))
			// return " And One Cent";
			return "Cents One only";
		else
			return "Cents " + centsPart + " only ";
		// return " And " + centsPart + " Cents";
	}

	private String formatDigit(int value) {
		int number = value;
		String prefix = ""; // 正负号前缀。

		if (number < 0) {
			number = -number;
			prefix = "Negative ";
		}

		String result = "";
		int index = 0;
		do {
			int n = number % 1000;
			if (n != 0) {
				result = formatLessThanOneThousand(n) + MAJORS[index] + result;
			}
			index++;
			number /= 1000;
			this.cValue = number;
		} while (number > 0);

		return (prefix + result).trim();
	}

	private String formatLessThanOneThousand(int value) {
		int number = value;
		String result = "";

		if (number % 100 < 20) {// 前两位数的值在20以内。
			result = NUMBERS[number % 100];
			number /= 100;
		} else {// 前两位数的值在20以外。
			result = NUMBERS[number % 10];// 个位
			number /= 10;
			if (result.trim().equals("")) {
				result = TENS[number % 10] + result;// 十位&个位
			} else {
				result = TENS[number % 10] + "-" + result;// 十位&个位
			}
			number /= 10;
		}
		if (number == 0) {
			if (this.cValue > (value + 100))
				return " and " + result;
			else
				return result;
		} else {
			if (result.trim().equals("")) {
				return NUMBERS[number] + " Hundred "; // 百位&十位&个位。
			} else {
				return NUMBERS[number] + " Hundred and " + result; // 百位&十位&个位。
			}
		}
	}

}
